package com.hong.spring.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.util.concurrent.Future;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;

import javax.net.ssl.SSLException;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author: csh
 * @Date: 2021/1/20 10:38
 * @Description:客户端
 */
@Log4j2
public class WebsocketClient {

    @Autowired
    private Bootstrap clientBootstrap;

    @Autowired
    private NioEventLoopGroup eventExecutors;
    /**ws url */
    private URI uri;
    /**sslCtx */
    private SslContext sslCtx;
    /**handler */
    private WebSocketClientHandler handler;

    @Autowired
    private WebsocketChannelInitializer websocketChannelInitializer;

    private Channel channel;

    public Channel getChannel() {
        return channel;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());


    /**主机地址 */
    private String host;
    /**端口号 */
    private int port;



    public void close() {
        Future<?> bossGroupFuture = eventExecutors.shutdownGracefully();
        try {
            bossGroupFuture.await();
            System.out.println("websocket客户端服务停止中...");
        } catch (InterruptedException ignore) {
            ignore.printStackTrace();
        }
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public URI getUri() {
        return uri;
    }

    public void setUri(URI uri) {
        this.uri = uri;
    }

    public SslContext getSslCtx() {
        return sslCtx;
    }

    public void setSslCtx(SslContext sslCtx) {
        this.sslCtx = sslCtx;
    }

    public WebSocketClientHandler getHandler() {
        return handler;
    }

    public void setHandler(WebSocketClientHandler handler) {
        this.handler = handler;
    }

    public void run() {
        new Thread(()->{
            try {
                String scheme = uri.getScheme() == null ? "ws" : uri.getScheme();
                final String host = uri.getHost() == null ? "127.0.0.1" : uri.getHost();
                final int port = uri.getPort();
                if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
                    System.out.println("只支持ws");
                    return;
                }

                final boolean ssl = "wss".equalsIgnoreCase(scheme);
                if (ssl) {
                    sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
                } else {
                    sslCtx = null;
                }
                handler = new WebSocketClientHandler(WebSocketClientHandshakerFactory.newHandshaker(uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));
                clientBootstrap.group(eventExecutors)
                        .channel(NioSocketChannel.class)
                        .handler(websocketChannelInitializer);
                System.out.println("client ready");
                Channel channel = clientBootstrap.connect(host, port).sync().channel();
                this.channel = channel;
                //等待握手完成
                handler.handshakeFuture().sync();
                log.info("握手完成！");
                channel.closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (SSLException e) {
                e.printStackTrace();
            } finally {
                System.out.println("触发关闭连接池！");
                eventExecutors.shutdownGracefully();
            }
        }).start();
    }
}
